package ua.kratik.seabattle.web;

import java.io.BufferedWriter;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentLinkedQueue;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import ua.kratik.seabattle.domain.BattleRules;
import ua.kratik.seabattle.domain.User;
import ua.kratik.seabattle.game.Admiral;
import ua.kratik.seabattle.game.Coordinates;
import ua.kratik.seabattle.game.Enemy;
import ua.kratik.seabattle.game.enums.ShootResult;
import ua.kratik.seabattle.service.api.BattleRulesService;
import ua.kratik.seabattle.service.api.CountryService;
import ua.kratik.seabattle.service.api.UserService;

@Controller
public class MainController {

	private static Logger logger = LoggerFactory
			.getLogger(MainController.class);

	@Autowired
	private UserService userService;

	@Autowired
	private CountryService countryService;

	@Autowired
	private BattleRulesService battleRulesService;

	private static final String IMAGE_SHIP = "ship.bmp";
	private static final String IMAGE_SEA = "sea.gif";

	// just shows seaMap
	@RequestMapping("/index.htm")
	public String index(HttpSession session, Map<String, Object> map) {
		Admiral admiral = (Admiral) session.getAttribute("admiral");
		map.put("seaMap", admiral.getMySeaMap());
		map.put("admiral", admiral);
		return "index";
	}


	@RequestMapping("/")
	public String home() {
		return "redirect:/login.htm";
	}

	@RequestMapping("login")
	public String loginPage() {
		return "login";
	}

	@RequestMapping(value = "login/chake", method = RequestMethod.POST)
	public String loginChake(HttpSession session, @RequestParam String email,
			@RequestParam String pass) throws WebLayerException {

		User user = userService.validateUser(email, pass);
		if (user != null) {
			Admiral admiral = new Admiral(user);
			session.setAttribute("admiral", admiral);
			logger.debug("Admiral '" + user.getEmail()
					+ "' was added to the current session attribute 'admiral'");
			Object obj = session.getServletContext().getAttribute(
					"loggedAdmirals");
			if (obj == null) {
				logger.error("Servlet context attribute 'loggedAdmirals' was not created");
				throw new WebLayerException(
						"Servlet context attribute 'loggedAdmirals' was not created");
			}
			Map<String, Admiral> loggedAdmirals = (Map<String, Admiral>) obj;
			loggedAdmirals.put(user.getEmail(), admiral);
			logger.debug("Admiral '"
					+ user.getEmail()
					+ "' was added to the servlet context attribute 'loggedAdmirals'");
			return "redirect:/index.htm";
		} else {
			return "redirect:/login.htm";
		}
	}

	@RequestMapping("logout.htm")
	public String onLogout(HttpSession session) {
		// session.removeAttribute("user");
		session.invalidate();
		return "redirect:/login.htm";
	}

	@RequestMapping("register")
	public String register(Map<String, Object> map) {
		map.put("user", new User());
		map.put("countries", countryService.findAll());
		return "register";
	}
	
	@RequestMapping("register/do_check_email.htm")
	public void onChackEmail(@RequestParam String email, HttpServletResponse responce){
		logger.debug("onChackEmail was called email = " + email);
		boolean isEmailFree = userService.isEmailFree(email);
		responce.setContentType("text/plain; charset=UTF-8" );
        try {
        	if(isEmailFree){
        		responce.getOutputStream().write(("Free").getBytes());
        	}else{
        		responce.getOutputStream().write(("Not free").getBytes());
        	}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@RequestMapping(value = "register/submit", method = RequestMethod.POST)
	public String registerSubmit(@ModelAttribute("user") User user,
			BindingResult result) {
		logger.debug("user email: " + user.getEmail());
		logger.debug("user birthsday: " + user.getBirthsday());
		userService.add(user);
		return "redirect:/login.htm";
	}

	// ============== GAME =====================
	@RequestMapping("autolayout.htm")
	public String onAutolayout(HttpSession session) {
		Admiral admiral = (Admiral) session.getAttribute("admiral");
		logger.debug("Starting autolayout for admiral ");
		admiral.autoLocateShips();
		logger.debug("Autolayout finished");
		return "redirect:/index.htm";
	}

	@RequestMapping("chuse_default_rules.htm")
	public String onChuseDefaultRules(HttpSession session) {
		// get current admiral
		Admiral admiral = (Admiral) session.getAttribute("admiral");
		// find default rules
		BattleRules rules = battleRulesService.findById(1);
		logger.debug("Bttle rules were found: " + rules.getRuleName());
		// set default rules
		admiral.setBattleRules(rules);
		logger.debug("Battle rules were set: " + rules.getRuleName());
		return "redirect:/index.htm";
	}

	@SuppressWarnings("unchecked")
	@RequestMapping("random_play.htm")
	public String onPlay(HttpSession session) {
		// get current admiral
		Admiral admiral = (Admiral) session.getAttribute("admiral");
		// get all waiting users
		ConcurrentLinkedQueue<Admiral> waitingAdmirals = 
				(ConcurrentLinkedQueue<Admiral>) session.getServletContext()
				.getAttribute("waitingAdmirals");
		// find waiting user with appropriate rules
		Iterator<Admiral> it = waitingAdmirals.iterator();
		Admiral a;
		boolean enemyChusen = false;
		while(it.hasNext() && !enemyChusen){
			a = it.next();
			if (admiral.areRulesEqual(a.getRules())) {
				admiral.setEnemy(a);
				it.remove();
				enemyChusen = true;
				logger.debug("Admiral '" + a.getEmail() 
						+ "' was removed from the servlet context attribute 'waitingAdmirals'");
			}
		}
		//add current user to the waiting list
		if (!enemyChusen){
			waitingAdmirals.add(admiral);
			logger.debug("Admiral '" + admiral.getEmail() 
					+ "' was added to the servlet context attribute 'waitingAdmirals'");
		}

		return "redirect:/index.htm";
	}
	
	@RequestMapping("/shoot.htm")
	public String onShoot(@RequestParam Integer x, @RequestParam Integer y,
			HttpSession session) {
		Admiral me = (Admiral) session.getAttribute("admiral");
		Coordinates c = new Coordinates(x, y);
		ShootResult sResult = me.getEnemy().shoot(c);
		if (sResult != ShootResult.SHOOT_PROHIBITED) {
			me.updateEnemyMap(c, sResult);
		}else{
			
		}
		return "redirect:/index.htm";
	}
}
